home *** CD-ROM | disk | FTP | other *** search
- /* PDUtilities.c: Utility routines for ProjectDrag
- *
- * A set of applets for drag and drop source control by Tim Maroney.
- * See develop, issue 23 for details.
- *
- * Built on DropShell by Leonard Rosenthol, Stephan Somogyi, and Marshall Clow,
- * and using the MoreFiles utilities by Jim Luther.
- *
- * This software is free, but don't modify and redistribute it without
- * changing the status window to indicate your name and your changes!
- */
-
- #include <Errors.h>
- #include <Folders.h>
- #include <Resources.h>
- #include <Script.h>
- #include <Dialogs.h>
- #include <ToolUtils.h>
- #include <Finder.h>
-
- #include "PDUtilities.h"
- #include "MoreFilesExtras.h"
- #include "DSUtils.h"
-
-
- /* utility routine to find (and create if necesssary) the ProjectDrag
- * Preferences folder inside the System Folder's Preferences folder
- */
-
- OSErr FindPreferencesFolder(short *vRefNum, long *folderID)
- {
- OSErr err = noErr;
- FSSpec ourFolder;
- Boolean isFolder;
-
- err = FindFolder (kOnSystemDisk, kPreferencesFolderType, true, &ourFolder.vRefNum, &ourFolder.parID);
- if (err != noErr)
- return err;
- GetIndString(ourFolder.name, kProjectDragStrings, kPrefsFolderName);
- err = DirIDFromFSSpec(&ourFolder, folderID, &isFolder);
- if (err == dirNFErr || err == fnfErr)
- err = FSpDirCreate(&ourFolder, smSystemScript, folderID);
- else if (!isFolder)
- err = dirNFErr; /* isn't there an isAFileErr? */
- if (err == noErr)
- *vRefNum = ourFolder.vRefNum;
- return err;
- }
-
-
- void AppendString(unsigned char *original, unsigned char *append)
- // append one Pascal string to another
- {
- int length;
- if (original == 0 || append == 0) return;
- length = append[0];
- if (original[0] + length > 255)
- length = 255 - original[0];
- if (length == 0) return;
- BlockMove(append + 1, original + original[0] + 1, length);
- original[0] += length;
- }
-
-
- OSErr ProcessFileOrFolder(FSSpec *spec, void (*doFile)(FSSpec *spec, Boolean doingFolder),
- OSErr (*doFolder)(short vRefNum, long folderID,
- void (*doFile)(FSSpec *spec, Boolean doingFolder)))
- {
- if (spec->name[0] == 0)
- {
- return (*doFolder)(spec->vRefNum, spec->parID, doFile);
- }
- else
- {
- CInfoPBRec pb;
-
- pb.hFileInfo.ioVRefNum = spec->vRefNum;
- pb.hFileInfo.ioDirID = spec->parID;
- pb.hFileInfo.ioNamePtr = spec->name;
- pb.hFileInfo.ioFDirIndex = (spec->name[0] == 0) ? -1 : 0;
- PBGetCatInfoSync(&pb);
- if (pb.hFileInfo.ioResult != noErr) return pb.hFileInfo.ioResult;
- if ((pb.hFileInfo.ioFlAttrib & 0x10) == 0)
- (*doFile)(spec, false);
- else
- (*doFolder)(spec->vRefNum, pb.dirInfo.ioDrDirID, doFile);
- }
- return noErr;
- }
-
-
- OSErr ProcessFolder(short vRefNum, long folderID, void (*doFile)(FSSpec *spec, Boolean doingFolder))
- {
- CInfoPBRec pb;
- OSErr err = noErr;
-
- /* for all the items in the folder */
- for (pb.hFileInfo.ioFDirIndex = 1; err == noErr && !gDone; pb.hFileInfo.ioFDirIndex++)
- {
- FSSpec spec;
- Boolean isFile;
-
- spec.name[0] = 0;
- pb.hFileInfo.ioNamePtr = spec.name;
- pb.hFileInfo.ioVRefNum = vRefNum;
- pb.hFileInfo.ioDirID = folderID;
- err = PBGetCatInfoSync(&pb);
- if (err != noErr) break;
-
- isFile = ((pb.hFileInfo.ioFlAttrib & 0x10) == 0);
-
- if (isFile)
- {
- spec.vRefNum = vRefNum;
- spec.parID = folderID;
- (*doFile)(&spec, true);
- }
- else
- {
- ProcessFolder(vRefNum, pb.dirInfo.ioDrDirID, doFile);
- }
- }
- if (err == fnfErr)
- err = noErr; /* end of loop */
- return err;
- }
-
-
- OSErr MakeFullPathName(FSSpec *spec, Str255 fullPathName)
- {
- CInfoPBRec pb;
- OSErr err = noErr;
- short vRefNum = spec->vRefNum;
- long folderID = spec->parID;
-
- if (spec->name[0] == 0)
- fullPathName[0] = 0;
- else
- BlockMove(spec->name, fullPathName, spec->name[0] + 1);
-
- do
- {
- Str31 folderName;
-
- folderName[0] = 0;
- pb.hFileInfo.ioNamePtr = folderName;
- pb.hFileInfo.ioVRefNum = vRefNum;
- pb.hFileInfo.ioDirID = folderID;
- pb.hFileInfo.ioFDirIndex = -1;
- err = PBGetCatInfoSync(&pb);
- if (err == noErr)
- {
- if (fullPathName[0] > 0)
- BlockMove(fullPathName + 1, fullPathName + 2 + folderName[0], fullPathName[0]);
- BlockMove(folderName + 1, fullPathName + 1, folderName[0]);
- fullPathName[folderName[0] + 1] = ':';
- fullPathName[0] += folderName[0] + 1;
- folderID = pb.dirInfo.ioDrParID;
- }
- } while (err == noErr && folderID != fsRtParID);
- return err;
- }
-
-
- OSErr ExtractCKID(FSSpec *file, CKIDHandle *theCKID)
- {
- /* open the resource file */
- short refNum = FSpOpenResFile(file, fsRdPerm);
- if (refNum < 0)
- return ResError();
-
- /* get the CKID from it and clone it */
- *theCKID = (CKIDHandle) Get1IndResource('ckid', 1);
- if (*theCKID == NULL)
- {
- CloseResFile(refNum);
- return resNotFound;
- }
- DetachResource((Handle)*theCKID);
-
- /* close the resource file */
- CloseResFile(refNum);
- return noErr;
- }
-
- static Boolean IsCommandKey(EventRecord *event)
- {
- return (event->what == keyDown) && ((event->modifiers & cmdKey) != 0);
- }
-
- pascal Boolean ProjectDragIdleProc(EventRecord *theEvent, long *sleepTime, RgnHandle *mouseRgn)
- {
- if (theEvent->what == nullEvent)
- {
- *mouseRgn = NULL;
- *sleepTime = 10;
- }
- else if (!IsCommandKey(theEvent) && IsDialogEvent(theEvent))
- {
- DialogPtr dialog;
- short itemHit;
-
- DialogSelect(theEvent, &dialog, &itemHit);
- }
- return false;
- }
-
-
- short ReplaceString(Handle baseText, StringPtr key, StringPtr substitutionText)
- {
- OSErr err = noErr;
- Handle h = NULL;
-
- err = PtrToHand(substitutionText + 1, &h, substitutionText[0]);
- if (err != noErr) return err;
- err = ReplaceText(baseText, h, key);
- DisposeHandle(h);
- return err;
- }
-
-
- void ReplaceInIndString(StringPtr stringOut, short strListID, short strIndex,
- StringPtr param1, StringPtr param2,
- StringPtr param3, StringPtr param4)
- {
- Handle h;
- OSErr err;
-
- GetIndString(stringOut, strListID, strIndex);
- err = PtrToHand(stringOut + 1, &h, stringOut[0]);
- if (param1 != NULL)
- err = ReplaceString(h, "\p<1>", param1);
- else
- err = ReplaceString(h, "\p<1>", "\p");
- if (param2 != NULL)
- err = ReplaceString(h, "\p<2>", param2);
- else
- err = ReplaceString(h, "\p<2>", "\p");
- if (param3 != NULL)
- err = ReplaceString(h, "\p<3>", param3);
- else
- err = ReplaceString(h, "\p<3>", "\p");
- if (param4 != NULL)
- err = ReplaceString(h, "\p<4>", param4);
- else
- err = ReplaceString(h, "\p<4>", "\p");
- stringOut[0] = GetHandleSize(h);
- BlockMoveData(*h, stringOut + 1, stringOut[0]);
- DisposeHandle(h);
- }
-
-
- long LineSize(StringPtr theLine, long maxSize)
- {
- long length;
- for (length = 0; maxSize > 0; theLine++, maxSize--)
- {
- length++;
- if (*theLine == '\n') break; /* after incrementing the length to include this */
- }
- return length;
- }
-
-
- Boolean MatchLineUntilChar(StringPtr line1, long len1, StringPtr line2, long len2, char untilChar)
- {
- long i, j;
-
- for (i = j = 0; i < len1 && j < len2; )
- {
- if (untilChar != 0 && line2[j] == untilChar)
- return true; /* we reached the stop character */
-
- if (line1[i] == '\n' || line2[j] == '\n')
- {
- /* if we reach the end of line on one, we must reach it on the other */
- return line1[i] == '\n' && line2[j] == '\n';
- }
- else if (line1[i] == ' ' || line1[i] == '\t')
- {
- /* any amount of white space matches any other */
- if (line2[j] != ' ' && line2[j] != '\t')
- return false;
- i++, j++; /* we know these characters are blanks */
- while (i < len1 && line1[i] == ' ' || line1[i] == '\t')
- i++;
- while (j < len2 && line2[j] == ' ' || line2[j] == '\t')
- j++;
- }
- else if (line1[i] != line2[j])
- {
- return false;
- }
- else /* still matching, go on to next character */
- {
- i++, j++; /* this is here instead of in "for" because
- * these variables get changed internally
- */
- }
- }
-
- /* if we get here, all characters should have been exhausted (as am I);
- * the only exception is that one may still have an unexhausted end of line...
- */
- return (len1 == i || (len1 == i + 1 && line1[i] == '\n'))
- && (len2 == j || (len2 == j + 1 && line2[j] == '\n'));
- }
-
-
- Boolean MatchLine(StringPtr line1, long len1, StringPtr line2, long len2)
- {
- return MatchLineUntilChar(line1, len1, line2, len2, 0);
- }
-
-
- OSErr GetFileData(FSSpec *file, Handle *fileData, short *refNum)
- {
- OSErr err;
- IOParam io;
- long count;
-
- *fileData = NULL;
- *refNum = -1;
-
- err = FSpOpenDF(file, fsRdWrPerm, refNum);
- if (err != noErr) goto ErrorExit;
- err = GetEOF(*refNum, &count);
- if (err != noErr) goto ErrorExit;
- *fileData = TempNewHandle(count, &err);
- if (err != noErr) goto ErrorExit;
- HLock(*fileData);
- io.ioCompletion = NULL;
- io.ioRefNum = *refNum;
- io.ioBuffer = **fileData;
- io.ioReqCount = count;
- io.ioPosMode = fsFromStart;
- io.ioPosOffset = 0;
- PBReadAsync((ParmBlkPtr)&io);
- while (io.ioResult == 1)
- {
- EventRecord event;
- WaitNextEvent(everyEvent, &event, 10, NULL);
- }
- err = io.ioResult;
- if (err != noErr) goto ErrorExit;
- HUnlock(*fileData);
- return noErr;
-
- ErrorExit:
- if (*refNum != -1)
- {
- FSClose(*refNum);
- *refNum = -1;
- }
- if (*fileData != NULL)
- {
- DisposeHandle(*fileData);
- *fileData = NULL;
- }
- return err;
- }
-
-
- OSErr WriteFileWithHeader(short refNum, Handle fileData, long startOffset, StringHandle header)
- {
- OSErr err = noErr;
- Byte state;
- IOParam io;
-
- /* zero the file */
- err = SetEOF(refNum, 0);
- if (err != noErr) return err;
- err = SetFPos(refNum, fsFromStart, 0);
- if (err != noErr) return err;
-
- /* write out the header to the file */
- if (header != NULL)
- {
- state = HGetState(header);
- HLock(header);
- io.ioCompletion = NULL;
- io.ioRefNum = refNum;
- io.ioBuffer = *header;
- io.ioReqCount = GetHandleSize(header);
- io.ioPosMode = fsFromStart;
- io.ioPosOffset = 0;
- PBWriteAsync((ParmBlkPtr)&io);
- while (io.ioResult == 1)
- {
- EventRecord event;
- WaitNextEvent(everyEvent, &event, 10, NULL);
- }
- err = io.ioResult;
- HSetState(header, state);
- if (err != noErr) return err;
- }
-
- /* copy the data fork from the start offset to the file */
- state = HGetState(fileData);
- HLock(fileData);
- io.ioCompletion = NULL;
- io.ioRefNum = refNum;
- io.ioBuffer = (*fileData) + startOffset;
- io.ioReqCount = GetHandleSize(fileData) - startOffset;
- io.ioPosMode = fsFromStart;
- io.ioPosOffset = GetHandleSize(header);
- PBWriteAsync((ParmBlkPtr)&io);
- while (io.ioResult == 1)
- {
- EventRecord event;
- WaitNextEvent(everyEvent, &event, 10, NULL);
- }
- err = io.ioResult;
- HSetState(fileData, state);
- if (err != noErr) return err;
-
- return noErr;
- }
-
-
- /* SetFileLabel was cribbed from ChangeFDFlags in MoreFilesExtras.c */
-
- OSErr SetFileLabel(FSSpec *file, short label, short *oldLabel)
- {
- CInfoPBRec pb;
- OSErr err;
- short realVRefNum;
- long parID;
-
- if (file->name[0] == 0)
- pb.hFileInfo.ioNamePtr = NULL;
- else
- pb.hFileInfo.ioNamePtr = file->name;
- pb.hFileInfo.ioVRefNum = file->vRefNum;
- pb.hFileInfo.ioDirID = file->parID;
- pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */
- err = PBGetCatInfoSync(&pb);
- if ( err == noErr )
- {
- parID = pb.hFileInfo.ioFlParID; /* save parent dirID for BumpDate call */
-
- if (oldLabel != NULL)
- *oldLabel = (pb.hFileInfo.ioFlFndrInfo.fdFlags >> 1) & kColor;
-
- pb.hFileInfo.ioFlFndrInfo.fdFlags &= ~kColor; /* clear the bits */
- pb.hFileInfo.ioFlFndrInfo.fdFlags |= (label << 1) & kColor; /* set the bits */
-
- pb.hFileInfo.ioDirID = file->parID;
- err = PBSetCatInfoSync(&pb); /* now, save the new information back to disk */
-
- if ( (err == noErr) && (parID != fsRtParID) ) /* can't bump fsRtParID */
- {
- /* get the real vRefNum in case a full pathname was passed */
- err = DetermineVRefNum((StringPtr)file->name, file->vRefNum, &realVRefNum);
- if ( err == noErr )
- {
- err = BumpDate(realVRefNum, parID, NULL);
- /* and bump the parent directory's mod date to wake up the Finder */
- /* to the change we just made */
- }
- }
- }
- return ( err );
- }
-